Module Triggers

Tuple Documentation of module_triggers.py
Each trigger contains the following fields:
1) Check interval: How frequently this trigger will be checked.
2) Delay interval: Time to wait before applying the consequences of the trigger.
    After its conditions have been evaluated as true.
3) Re-arm interval: How much time must pass after applying the consequences of the trigger for the trigger to become active again.
    You can put the constant ti_once here to make sure that the trigger never becomes active again after it fires once.
4) Conditions block (list): This must be a valid operation block. See header_operations.py for reference.
    Every time the trigger is checked, the conditions block will be executed.
    If the conditions block returns true, the consequences block will be executed.
    If the conditions block is empty, it is assumed that it always evaluates to true.
5) Consequences block (list): This must be a valid operation block. See header_operations.py for reference.

The regular triggers of module_triggers.py, called only triggers, are a bit more complex and versatile than their simpler counterparts, but are largely the same. This kind of triggers is however more important because they are also getting used in the mission templates. Triggers within module_triggers.py fire however only at the world map. Let's examine the structure of a trigger: (check_interval, delay_interval, re-arm_inverval, [conditions_block], [operations_block]),[1]

As you can see, there are more fields present here than there are at the simple triggers. Now let's examine them one by one.

  • The check interval is absolutely the same as before - how often the trigger fires;
  • The delay interval is how much the consequences should be delayed once the conditions are true;
  • The re-arm interval is how long the trigger should remain inactive once the consequences are applied;
  • The conditions block contains the code that needs to be checked in order to allow for the consequences to fire;
  • The consequences block is where the majority of your ocde is usually located, it will be executed once the conditions are evaluated to true and the delay interval wears off.

Now, how would our senseless simple trigger from the chapter before look like as a regular trigger?

								
									(24, 0, 0, [], [
  (try_begin),
      (lt, "$player_honor", 0),
      (troop_add_gold, "trp_player", 100),
  (try_end),
  ]),

This is perfectly valid, but it's frankly kind of stupid if we are going to use a regular trigger. Let's buff up the rewards and rework the code a bit in order to make use of the systems that this trigger allows us:

								
									(24, 6, 48, [
  (lt, "$player_honor", 0),
  ], [
  (troop_add_gold, "trp_player", 400),
  ]),

Now, every 24 hours this trigger will evaluate the player's honour. If it's below zero, six hours will pass, keeping the player on edge (okay, not really), and then he or she will be awarded four hundred gold. However, the trigger will not fire for the next 48 hours, which kind of compensates for the greater reward. Yes, the trigger is still dumb, but it serves as a nice example.

Regular triggers also have (in other files than module_triggers.py) their special conditions, most of which related to missions like for example ti_before_mission_start or ti_on_agent_spawn. Those triggers are listed in header_triggers.py and will all get explained at their respective sections at which they can get used.

Remarkable Notes

  1. The check, delay and re-arms interval of triggers within module_triggers.py are in hours, and of triggers within module_mission_templates.py they are in seconds. Setting a zero as check interval lets the trigger however fire at every frame, it is not affected by the party movement or difference in time flow. It even runs when your party stops and the world map pauses.[2]
  2. Avoid too many specific triggers.[3]
  3. Local variables are not transferred between conditions and consequences. In other words, you will need to store a variable again to modify it in the consequences if you have already stored it to check it.
  4. When dealing with triggers with special conditions, you are likely to need to check their parameters using the operations store_trigger_param_*. Consult header_triggers.py or the respective section for a list of parameters for each trigger.

Randomness of Triggers

(simple) triggers a bit random, Leonion, Modding Q&A

Randomly Delayed Trigger [4]

Now you know that the check intervals at triggers already fire randomly. What now if you want a randomly delayed trigger instead? Say, instead of a trigger that fires once after 24 hours, like this one

								
									(2, 24, ti_once, [], [<your code>]),
								
							

You want one that fires once but randomly delayed between 24 and 48 hours after it got triggered? In that case you should use two triggers and global variables to do it, like you can see in the following example

								
									(2,0,ti_once, [(store_random_in_range, "$g_delayed", 24, 49), (assign, "$g_run", 0),], []),

(1,0,ti_once, [(val_add, "$g_run",1), (gt,"$g_run","$g_delayed"),], [<your code>]),